<?php
class articles {
  function __construct() {
  }

  public function listart() {
	$errcode = 0;
	$errmess = '';
    $data = array();
	
    try
    {
// Только зарегистрированные пользователи могут видеть данные
		if( !isset($_SESSION['user_id']) || $_SESSION['user_id'] == 0 )
			throw new Exception(ERR_M::TIMEOUT_ERROR, 999);

// Find - услуга общего пользования. Поэтому, маска должна быть READ_ANY
		$rwd = $_SESSION['priv']->articles->rwd;
		if( ( $rwd & PERM_BITS::READ_ANY ) == 0 ) throw new Exception(ERR_M::DATA_OPER_DISABLED, 99);

// Открываем базу данных
		$db = App::me()->dbOpen();	

// Фильтр привилегий
		if( $rwd & PERM_BITS::READ_OTH ) $whs = '1 = 1';
		elseif( $rwd & PERM_BITS::READ_GRP ) 
			$whs = 'art_user_id IN (SELECT user_id FROM users WHERE cat_id = '.$_SESSION['cat_id'].')';
		elseif( $rwd & PERM_BITS::READ_OWN ) $whs = 'art_user_id = '.$_SESSION['user_id'];
		else $whs = '1 = 0';
		
// Формируем запрос
		$sql =	'SELECT art_id, art_code, art_met_id, met_name, art_full_name FROM articles '.
				'LEFT JOIN metrics ON met_id = art_met_id '.
				'WHERE '.$whs.' ORDER BY art_code';
		$recset = $db->query($sql);                  
        while( $row = $recset->fetch(PDO::FETCH_ASSOC) ) {
            $unit = new stdClass;
            $unit->key = $row['art_id'];
			$unit->title = $row['art_code'];
			$unit->met_id = $row['art_met_id'];
			$unit->met_name = $row['met_name'];			
			$unit->description = $row['art_full_name'];
            $unit->isFolder = false;
            $unit->isLazy = false;
            $data[] = $unit;
        }
        $recset->closeCursor();
 
    }
	catch (PDOException $e) {
		$errcode = 1;
		$errmess = ERR_M::DATABASE_ERROR;
	}
    catch ( Exception $e ) {
		$errcode = $e->getCode();
		$errmess = $e->getMessage();
	}

	if( $errcode ) {
		$unit = new stdClass;
		$unit->title = '';
		$unit->errcode = $errcode;
		$unit->errmess = $errmess;
		return array($unit);
	}
	else return $data;
  }
  
  public function find() {
	$errcode = 0;
	$errmess = '';
    $data = array();
	
    try
    {
// Только зарегистрированные пользователи могут видеть данные
		if( !isset($_SESSION['user_id']) || $_SESSION['user_id'] == 0 )
			throw new Exception(ERR_M::TIMEOUT_ERROR, 999);

// Find - услуга общего пользования. Поэтому, маска должна быть READ_ANY
		$rwd = $_SESSION['priv']->articles->rwd;
		if( ( $rwd & PERM_BITS::READ_ANY ) == 0 ) throw new Exception(ERR_M::DATA_OPER_DISABLED, 99);

// Проверяем данные
        $term   = isset($_REQUEST["term"]) ? trim(strip_tags($_REQUEST["term"])) : '';
        if ($term == '')
			throw new Exception(ERR_M::PROTOCOL_ERROR, 1);
   
// Открываем базу данных
		$db = App::me()->dbOpen();	

// Фильтр привилегий
		if( $rwd & PERM_BITS::READ_OTH ) $whs = '1 = 1';
		elseif( $rwd & PERM_BITS::READ_GRP ) 
			$whs = 'art_user_id IN (SELECT user_id FROM users WHERE cat_id = '.$_SESSION['cat_id'].')';
		elseif( $rwd & PERM_BITS::READ_OWN ) $whs = 'art_user_id = '.$_SESSION['user_id'];
		else $whs = '1 = 0';
		
// Формируем запрос. !!!Только артикли со спецификацией
		$sql =  "SELECT art_id, art_code, art_full_name, art_met_id, met_name, ".
				"IF(( SELECT 1 FROM specmodel WHERE spm_art_id=art_id limit 1 ),1,0) AS spm_num ".
				"FROM articles ".
				"LEFT JOIN metrics ON met_id = art_met_id ".
				"WHERE ( art_code LIKE ".$db->quote("%".$term."%").
				" OR art_full_name LIKE ".$db->quote("%".$term."%").' ) AND '.$whs." ORDER BY art_code";
					
		$recset = $db->query($sql);                  
        while( $row = $recset->fetch(PDO::FETCH_ASSOC) ) {
			if( !$row['spm_num'] ) continue;
            $item = new stdClass;
            $item->art_id = $row['art_id'];
			
			$num = mb_strlen($term,'UTF-8');
			$pos = mb_stripos( $row['art_code'], $term, 0, 'UTF-8');
			if( !is_bool($pos) ) {
				$bterm = mb_substr($row['art_code'], $pos, $num, 'UTF-8');
				$name = preg_replace( '/'.$bterm.'/u', '<b>'.$bterm.'</b>', $row['art_code'] );				
			} else $name = $row['art_code'];
			$pos = mb_stripos( $row['art_full_name'], $term, 0, 'UTF-8');
			if( !is_bool($pos) ) {
				$bterm = mb_substr($row['art_full_name'], $pos, $num, 'UTF-8');
				$full = preg_replace( '/'.$bterm.'/u', '<b>'.$bterm.'</b>', $row['art_full_name'] );				
			} else $full = $row['art_full_name'];
			
//			$sql =	"SELECT IF(( SELECT 1 FROM specmodel WHERE spm_art_id=".$item->art_id." limit 1 ),1,0) AS spm_num";
//			$rs = $db->query()
            $item->art_code = $name;
            $item->met_id = $row['art_met_id'];
            $item->met_name = $row['met_name'];
			$item->art_full_name = $full;
            $data[] = $item;
        }
        $recset->closeCursor();
 
    }
	catch (PDOException $e) {
		$errcode = 1;
		$errmess = ERR_M::DATABASE_ERROR;
	}
    catch ( Exception $e ) {
		$errcode = $e->getCode();
		$errmess = $e->getMessage();
	}
 
	return array('errcode'=>$errcode,'errmess'=>$errmess, 'data'=>$data);
  }
  
  
  public function insart() {

    $art_code		= isset($_POST['art_code']) ? trim(strip_tags($_POST['art_code'])) : '';
    $art_met_id		= isset($_POST['art_met_id']) ? trim(strip_tags($_POST['art_met_id'])) : '';
    $met_name		= isset($_POST['met_name']) ? trim(strip_tags($_POST['met_name'])) : '';
    $art_full_name	= isset($_POST['art_full_name']) ? trim(strip_tags($_POST['art_full_name'])) : '';
	
	$errcode = 0;
	$errmess = '';
	$data = new stdClass;
	
    try
    {
// Только зарегистрированные пользователи могут вносить данные
		if( !isset($_SESSION['user_id']) || $_SESSION['user_id'] == 0 )
			throw new Exception(ERR_M::TIMEOUT_ERROR, 999);
		$art_user_id = $_SESSION['user_id'];
		
//Есть ли разрешение на вставку записей
		$rwd = $_SESSION['priv']->articles->rwd;
		if( ($rwd & PERM_BITS::WRITE_OWN) == 0 ) throw new Exception(ERR_M::DATA_OPER_DISABLED, 99);

// Все ли данные переданы
		$errdata = "";
		
// art_code
		if( $art_code == '' ) $errdata .= ($errdata?'<br>':'')."- Не указан шифр изделия.";
		else $art_code = mb_strtoupper( $art_code, 'UTF-8');

// art_met_id
		if( !ctype_digit($art_met_id) || $art_met_id == '0' ) 
			$errdata .= ($errdata?'<br>':'')."- Не указана метрива для изделия.";

// art_full_name
		if( $art_full_name == '' ) $errdata .= ($errdata?'<br>':'')."- Не задано описание изделия.";
		else $art_full_name = mb_substr( $art_full_name, 0, 255, 'UTF-8');

//				
// Если есть ошибки - можно уже закончить
//
		if( $errdata ) throw new Exception($errdata, 1);
		
// Открываем базу данных
		$db = App::me()->dbOpen();
		
// Может быть шифр уже существует
		
		$sqlreq =	'SELECT art_code FROM articles WHERE art_code = '.$db->quote($art_code);
		$recset = $db->query( $sqlreq );		
		$row = $recset->fetch(PDO::FETCH_ASSOC);
		if( $row ) {
			throw new Exception('В справочнике уже есть запись с таким шифром.', 1);
        }    
		$recset->closeCursor();

// Пишем данные
		$sql =	'INSERT INTO articles ( art_code, art_met_id, art_full_name, art_user_id ) '.
				'VALUES ('. $db->quote($art_code).", ".$db->quote($art_met_id).", ".
						$db->quote($art_full_name).", ".$db->quote($art_user_id). ")";
		$db->exec($sql);
		$art_id = $db->lastInsertId();
			
		$data->key = $art_id;
		$data->title = $art_code;
		$data->met_id = $art_met_id;
		$data->met_name = $met_name;
		$data->description = $art_full_name;
    }
	catch (PDOException $e) {
		$errcode = 1;
		$errmess = ERR_M::DATABASE_ERROR;
	}
    catch ( Exception $e ) {
		$errcode = $e->getCode();
		$errmess = $e->getMessage();
	}

	return array('errcode'=>$errcode,'errmess'=>$errmess, 'data'=>$data);
  }

  
  public function updart() {

    $art_id		= isset($_POST['art_id']) ? trim(strip_tags($_POST['art_id'])) : '';
    $art_code		= isset($_POST['art_code']) ? trim(strip_tags($_POST['art_code'])) : '';
    $art_met_id		= isset($_POST['art_met_id']) ? trim(strip_tags($_POST['art_met_id'])) : '';
    $met_name		= isset($_POST['met_name']) ? trim(strip_tags($_POST['met_name'])) : '';
    $art_full_name	= isset($_POST['art_full_name']) ? trim(strip_tags($_POST['art_full_name'])) : '';
	
	$errcode = 0;
	$errmess = '';
	$data = new stdClass;
	
    try
    {
// Только зарегистрированные пользователи могут вносить данные
		if( !isset($_SESSION['user_id']) || $_SESSION['user_id'] == 0 )
			throw new Exception(ERR_M::TIMEOUT_ERROR, 999);
		$art_user_id = $_SESSION['user_id'];
		
//Есть ли разрешение на вставку записей
		$rwd = $_SESSION['priv']->articles->rwd;
		if( ($rwd & PERM_BITS::WRITE_ANY) == 0 ) throw new Exception(ERR_M::DATA_OPER_DISABLED, 99);

// Все ли данные переданы
		$errdata = "";
		
// art_id
        if (!$art_id || !ctype_digit( $art_id ))
			throw new Exception(ERR_M::PROTOCOL_ERROR, 1);
        
// art_code
		if( $art_code == '' ) $errdata .= ($errdata?'<br>':'')."- Не указан шифр изделия.";
		$art_code = mb_strtoupper( $art_code, 'UTF-8');

// art_met_id
		if( !ctype_digit($art_met_id) || $art_met_id == '0' ) 
			$errdata .= ($errdata?'<br>':'')."- Не указана метрива для изделия.";

// art_full_name
		if( $art_full_name == '' ) $errdata .= ($errdata?'<br>':'')."- Не задано описание изделия.";
		$art_full_name = mb_substr( $art_full_name, 0, 255, 'UTF-8');

//				
// Если есть ошибки - можно уже закончить
//
		if( $errdata ) throw new Exception($errdata, 1);
		
// Открываем базу данных
		$db = App::me()->dbOpen();
		
// Проверяем задействована ли эта запись в других таблицах

		if( ( $errdata = $this->is_use_anyware( $db, $art_id )) != '' )
			throw new Exception( "Этот шаблон уже задействован в следующих документах:<br>".$errdata, 1);

// Есть ли разрешение на апдейт этой записи
		if( $rwd & PERM_BITS::WRITE_OTH ) $where = '1 = 1';
		elseif( $rwd & PERM_BITS::WRITE_GRP ) 
			$where = 'art_user_id IN (SELECT user_id FROM users WHERE cat_id = '.$_SESSION['cat_id'].')';
		elseif( $rwd & PERM_BITS::WRITE_OWN ) $where = 'art_user_id = '.$_SESSION['user_id'];
		else $where = '1 = 0';
		$where .= ' AND art_id = '.$db->quote($art_id);
		
		$sqlreq = 'SELECT COUNT(*) AS count FROM articles WHERE '.$where.' LIMIT 1';
		$recset = $db->query( $sqlreq );		
		$row = $recset->fetch(PDO::FETCH_ASSOC);
		if( !$row['count'] ) {
			throw new Exception(ERR_M::DATA_OWNER_DISABLED, 99);
        }    
		$recset->closeCursor();
		
// Может быть шифр уже существует
		
		$sqlreq =	'SELECT art_code FROM articles WHERE '.
					' art_code = '.$db->quote($art_code).
					' AND art_id != '.$db->quote($art_id);
		$recset = $db->query( $sqlreq );		
		$row = $recset->fetch(PDO::FETCH_ASSOC);
		if( $row ) {
			throw new Exception('В справочнике уже есть запись с таким шифром.', 1);
        }    
		$recset->closeCursor();

// Пишем данные
        $sqlreq =   'UPDATE articles SET '.
						'art_code = '.$db->quote($art_code).", ".
						'art_met_id = '.$db->quote($art_met_id).", ".
						'art_full_name = '.$db->quote($art_full_name)." ".
					'WHERE art_id = '.$db->quote($art_id);
		$db->exec($sqlreq);

		$data->key = $art_id;
		$data->title = $art_code;
		$data->met_id = $art_met_id;
		$data->met_name = $met_name;
		$data->description = $art_full_name;
    }
	catch (PDOException $e) {
		$errcode = 1;
		$errmess = ERR_M::DATABASE_ERROR;
	}
    catch ( Exception $e ) {
		$errcode = $e->getCode();
		$errmess = $e->getMessage();
	}

	return array('errcode'=>$errcode,'errmess'=>$errmess, 'data'=>$data);
  }

  
  public function delart() {
    $errmess = "";
	$errcode = 0;
		
    $art_id = isset($_POST['art_id']) ? trim(strip_tags($_POST['art_id'])) : '';

    try
    {
// Только зарегистрированные пользователи могут удалять данные
		if( !isset($_SESSION['user_id']) || $_SESSION['user_id'] == 0 )
			throw new Exception(ERR_M::TIMEOUT_ERROR, 999);

        if (!$art_id || !ctype_digit( $art_id ))
			throw new Exception(ERR_M::PROTOCOL_ERROR, 1);
        
// Есть ли разрешение на удаление хоть каких либо записей articles
		$rwd_art = $_SESSION['priv']->articles->rwd;
		if( ($rwd_art & PERM_BITS::DELETE_ANY) == 0 ) throw new Exception(ERR_M::DATA_OPER_DISABLED, 99);
		
// Есть ли разрешение на удаление хоть каких либо записей specmodel
		$rwd_spm = $_SESSION['priv']->specmodel->rwd;
		if( ($rwd_spm & PERM_BITS::DELETE_ANY) == 0 ) throw new Exception(ERR_M::DATA_OPER_DISABLED, 99);
		
// Открываем базу данных
		$db = App::me()->dbOpen();	

// Есть ли разрешение на удаление записей articles
		if( $rwd_art & PERM_BITS::DELETE_OTH ) $where = '1 = 1';
		elseif( $rwd_art & PERM_BITS::DELETE_GRP ) 
			$where = 'art_user_id IN (SELECT user_id FROM users WHERE cat_id = '.$_SESSION['cat_id'].')';
		elseif( $rwd_art & PERM_BITS::DELETE_OWN ) $where = 'art_user_id = '.$_SESSION['user_id'];
		else $where = '1 = 0';
		$where .= ' AND art_id = '.$db->quote($art_id);
		
		$sqlreq = 'SELECT COUNT(*) AS count FROM articles WHERE '.$where;
		$recset = $db->query( $sqlreq );		
		$row = $recset->fetch(PDO::FETCH_ASSOC);
		if( $row['count'] == 0 ) {
			throw new Exception(ERR_M::DATA_OWNER_DISABLED, 99);
        }    
		$recset->closeCursor();
		
// Есть ли разрешение на удаление записей specmodel
		if( $rwd_spm & PERM_BITS::DELETE_OTH ) $where = '1 = 1';
		elseif( $rwd_spm & PERM_BITS::DELETE_GRP ) 
			$where = 'spm_user_id IN (SELECT user_id FROM users WHERE cat_id = '.$_SESSION['cat_id'].')';
		elseif( $rwd_spm & PERM_BITS::DELETE_OWN ) $where = 'spm_user_id = '.$_SESSION['user_id'];
		else $where = '1 = 0';
		$where .= ' AND spm_art_id = '.$db->quote($art_id);
		
// Число записей спец. на которые есть права
		$sqlreq = 'SELECT COUNT(*) AS count FROM specmodel WHERE '.$where;
		$recset = $db->query( $sqlreq );		
		$row = $recset->fetch(PDO::FETCH_ASSOC);
		$nacc = $row['count'];
		$recset->closeCursor();

// Общее число записей спец. по этому артиклю
		$sqlreq = 'SELECT COUNT(*) AS count FROM specmodel WHERE spm_art_id = '.$db->quote($art_id);
		$recset = $db->query( $sqlreq );		
		$row = $recset->fetch(PDO::FETCH_ASSOC);
		$nall = $row['count'];
		$recset->closeCursor();

		if( $nacc != $nall ) {
			throw new Exception(ERR_M::DATA_OWNER_DISABLED, 99);
        }    
		
// Проверяем задействована ли эта запись в других таблицах

		if( ( $errdata = $this->is_use_anyware( $db, $art_id )) != '' )
			throw new Exception( "Удаляемые объекты задействованы в следующих документах:<br>".$errdata, 1);

// Удаляем записи из справочника
		try { 
			$db->beginTransaction();
			$sql =	'DELETE FROM specmodel WHERE spm_art_id = '.$db->quote($art_id).";\n".
					'DELETE FROM articles WHERE art_id = '.$db->quote($art_id).";";
			$db->exec($sql);
			$db->commit();
		} 
		catch(PDOExecption $e) { 
			$db->rollback(); 
			$errcode = 1;
			$errmess = ERR_M::DATABASE_ERROR;
		} 
	}
	catch (PDOException $e) {
		$errcode = 1;
		$errmess = ERR_M::DATABASE_ERROR;
	}
    catch ( Exception $e ) {
		$errcode = $e->getCode();
		$errmess = $e->getMessage();
	}

	return array('errcode'=>$errcode,'errmess'=>$errmess);
  }

  
  private function is_use_anyware( $db, $art_id ) {
	$sql =  "SELECT 'Изделия. Выписка со склада' as a FROM `products` WHERE prod_art_id = ".$db->quote($art_id).' LIMIT 1';
/*
			"UNION ".
			"SELECT 'Приход по скдаду' as a  FROM `outgoing` WHERE out_build_id IN (".$build_id_list.") ".
			"UNION ".
			"SELECT 'остатки по складу' as a  FROM `parcel` WHERE par_build_id IN (".$build_id_list.") ";
*/
	$recset = $db->query($sql);
	$errdata = '';
	while( $row = $recset->fetch(PDO::FETCH_ASSOC) ) {
		$errdata .= ($errdata?', ':'')."'".$row['a']."'"; 
	}
	return $errdata;
}
  
  
  public function listuni() {
  
    $data = new jqGridData();
    try
    {
// Только зарегистрированные пользователи могут видеть данные
		if( !isset($_SESSION['user_id']) || $_SESSION['user_id'] == 0 )
			throw new Exception(ERR_M::TIMEOUT_ERROR, 999);

		$rwd = $_SESSION['priv']->specmodel->rwd;
		if( !$rwd  ) throw new Exception(ERR_M::DATA_ACC_DISABLED, 99);

// Проверяем данные
        $art_id = isset($_REQUEST["art_id"]) ? $_REQUEST["art_id"] : '';
		if( $art_id == '' || !ctype_digit($art_id) )
			throw new Exception(ERR_M::PROTOCOL_ERROR, 1);

        $page    = ( isset($_REQUEST["page"]) && $_REQUEST["page"] > 0 ) ? $_REQUEST["page"] : 1;
        $limit    = ( isset($_REQUEST["rows"]) && $_REQUEST["rows"] > 0 ) ? $_REQUEST["rows"] : 1;
        $sidx    = ( isset($_REQUEST["sidx"]) && $_REQUEST["sidx"] != '' ) ? $_REQUEST["sidx"] : 'uni_name';
        $sord    = ( isset($_REQUEST["sord"]) && strtolower($_REQUEST["sord"]) == 'desc' ) ? 'DESC' : 'ASC';
        $search    = ( isset($_REQUEST["_search"]) && strtolower($_REQUEST["_search"]) == 'true') ? true : false;
 
// Открываем базу данных
		$db = App::me()->dbOpen();	

		switch( $sidx ) {
			case 'met_name': $sidx = 'met.met_name'; break;
			case 'uni_name': $sidx = 'uni.uni_name'; break;
			case 'uni_full': $sidx = 'uni.uni_full'; break;
		}
		
// Фильтр
        $whc = array();
		$whc[] = 'spm_art_id = '.$db->quote($art_id);
		
        if( $search )
        {
            if(isset($_REQUEST["uni_name"]) && $_REQUEST["uni_name"] != "") {
		    	$whc[] = "uni.uni_name LIKE " . $db->quote("%".$_REQUEST["uni_name"]."%");
            }
			
            if(isset($_REQUEST["uni_full"]) && $_REQUEST["uni_full"] != "") {
		    	$whc[] = "uni.uni_full LIKE " . $db->quote("%".$_REQUEST["uni_full"]."%");
            }
			
            if(isset($_REQUEST["met_name"]) && $_REQUEST["met_name"] != "") {
		    	$whc[] = "met.met_name LIKE " . $db->quote("%".$_REQUEST["met_name"]."%");
            }
			
            if(isset($_REQUEST["spm_amount"]) && $_REQUEST["spm_amount"] != "") {
		    	$whc[] = "spm.spm_amount LIKE " . $db->quote("%".$_REQUEST["spm_amount"]."%");
            }
		}

// Фильтр привилегий
		if( $rwd & PERM_BITS::READ_OTH ) $whc[] = '1 = 1';
		elseif( $rwd & PERM_BITS::READ_GRP ) 
			$whc[] = 'spm_user_id IN (SELECT user_id FROM users WHERE cat_id = '.$_SESSION['cat_id'].')';
		elseif( $rwd & PERM_BITS::READ_OWN ) $whc[] = 'spm_user_id = '.$_SESSION['user_id'];
		else $whc[] = '1 = 0';
		
        $whereclaus = (count($whc) != 0 ) ? " WHERE " . implode(" AND ", $whc) : "";
		unset($whc);
            
// Получаем количество записей с учетом фильтра
        $joins = 
                " INNER JOIN units AS uni ON uni.uni_id = spm.spm_uni_id ".
                " INNER JOIN metrics AS met ON met.met_id = uni.uni_met_id ";
            
        $sqlreq = "SELECT COUNT(*) AS count FROM specmodel AS spm ".$joins.$whereclaus;
        $recset = $db->query( $sqlreq );
		$row = $recset->fetch(PDO::FETCH_ASSOC);
		$count = $row['count'];
		$recset->closeCursor();
            
// Пустая таблица
        if ($count == 0)
			throw new Exception(ERR_M::SUCCESS, 0);
            
// Рассчитаем сколько всего страниц займут данные в БД
    	if( $count > 0 && $limit > 0) {
    		$total_pages = ceil($count/$limit);
    	} else {
    		$total_pages = 0;
    	}                  
 
		if ($page > $total_pages) $page=$total_pages;                  
 
		$start = $limit*$page - $limit;                   
		if($start < 0) $start = 0;                  
 
// Формируем запрос
		$sqlreq = 	"SELECT spm_id, spm_uni_id, uni_name, uni_full, spm_amount, met_id, met_name ".
					"FROM specmodel AS spm ".$joins.$whereclaus." ORDER BY ".$sidx." ".$sord.
		            " LIMIT ".$start.", ".$limit;

		$recset = $db->query($sqlreq);                  
 
// Формирование объекта для возврата
        
    	$data->page      = $page;
    	$data->total     = $total_pages;
    	$data->records   = $count;
    		
    // Строки данных для таблицы
		$i = 0;
		while($row = $recset->fetch(PDO::FETCH_ASSOC)) {
		
			$data->rows[$i]['id'] = $row['spm_id'];
			$data->rows[$i]['cell'] = array(
					$row['spm_id'],
					$row['spm_uni_id'],
					$row['uni_name'],
					$row['uni_full'],
				    $row['spm_amount'],
				    $row['met_id'],
				    $row['met_name']
		    );
		    $i++;
		}
    }
	catch (PDOException $e) {
		$data->userdata->errcode = 1;
		$data->userdata->errmess = ERR_M::DATABASE_ERROR;
	}
    catch ( Exception $e ) {
		$data->userdata->errcode = $e->getCode();
		$data->userdata->errmess = $e->getMessage();
	}
 
	return $data;
  }
  
  
  public function insuni() {

    $art_id		= isset($_POST['art_id']) ? trim(strip_tags($_POST['art_id'])) : '';
    $spm_uni_id		= isset($_POST['spm_uni_id']) ? trim(strip_tags($_POST['spm_uni_id'])) : '';
    $uni_name		= isset($_POST['uni_name']) ? trim(strip_tags($_POST['uni_name'])) : '';
    $spm_amount		= isset($_POST['spm_amount']) ? trim(strip_tags($_POST['spm_amount'])) : '';
	
	$errcode = 0;
	$errmess = '';
    try
    {
// Открываем базу данных
		$db = App::me()->dbOpen();	

// Только зарегистрированные пользователи могут вносить данные
		if( !isset($_SESSION['user_id']) || $_SESSION['user_id'] == 0 )
			throw new Exception(ERR_M::TIMEOUT_ERROR, 999);
		$spm_user_id = $_SESSION['user_id'];
		
		if( $art_id == '' || !ctype_digit($art_id) )
			throw new Exception(ERR_M::PROTOCOL_ERROR, 1);
			
//Есть ли разрешение на вставку записей
		$rwd = $_SESSION['priv']->specmodel->rwd;
		if( ($rwd & PERM_BITS::WRITE_OWN) == 0 ) throw new Exception(ERR_M::DATA_OPER_DISABLED, 99);

// Все ли данные переданы
		$errdata = "";
		
// uni_name			
		if( !$uni_name ) $errdata .= ($errdata?'<br>':'').'- Не указан шифр материала.';
		elseif( !$spm_uni_id || !ctype_digit( $spm_uni_id ) ) 
			$errdata .= ($errdata?'<br>':'').'- Не указан идентификатор материала.';
		else {
// Считываем данные из справочника
			$recset = $db->query('SELECT uni_name FROM units WHERE uni_id = '.$db->quote($spm_uni_id));                  
			$row = $recset->fetch(PDO::FETCH_ASSOC);
			if( !$row || $row['uni_name'] != $uni_name) {
				$errdata .= ($errdata?'<br>':'').'- Неправильно указан идентификатор материала.';
			}
			$recset->closeCursor();
		}

// spm_amount
		if( !$spm_amount )
			$errdata .= ($errdata?'<br>':'').'- Не указано количество материала.';
		else {
			$spm_amount = str_replace(',', '.', $spm_amount);
			if( !is_numeric( $spm_amount ) || $spm_amount <= 0 )
				$errdata .= ($errdata?'<br>':'')."- Неправильно указано количество материала.";
		}
		
//				
// Если есть ошибки - можно уже закончить
//
		if( $errdata ) throw new Exception($errdata, 1);
		
// Может быть материал уже существует
		$sqlreq =	'SELECT count(*) AS count FROM specmodel WHERE spm_uni_id = '.$db->quote($spm_uni_id).
					' AND spm_art_id = '.$db->quote($art_id);
		$recset = $db->query( $sqlreq );		
		$row = $recset->fetch(PDO::FETCH_ASSOC);
		if( $row['count'] != 0 ) {
			throw new Exception('В спецификации уже присутствует запись с шифром "'.$uni_name.'"', 1);
        }    
		$recset->closeCursor();

// Пишем данные
        $sqlreq =   'INSERT INTO specmodel ( spm_art_id, spm_uni_id, spm_amount, spm_user_id ) '.
                    'VALUES ('. $db->quote($art_id).", ".$db->quote($spm_uni_id).", ".
								$db->quote($spm_amount).", ".$db->quote($spm_user_id). ")";
												
		$db->exec($sqlreq);
    }
	catch (PDOException $e) {
		$errcode = 1;
		$errmess = ERR_M::DATABASE_ERROR;
	}
    catch ( Exception $e ) {
		$errcode = $e->getCode();
		$errmess = $e->getMessage();
	}

	return array('errcode'=>$errcode,'errmess'=>$errmess);
  }

  public function upduni() {

    $spm_id		= isset($_POST['id']) ? trim(strip_tags($_POST['id'])) : '';
    $art_id	= isset($_POST['art_id']) ? trim(strip_tags($_POST['art_id'])) : '';
    $spm_uni_id	= isset($_POST['spm_uni_id']) ? trim(strip_tags($_POST['spm_uni_id'])) : '';
    $uni_name	= isset($_POST['uni_name']) ? trim(strip_tags($_POST['uni_name'])) : '';
    $spm_amount	= isset($_POST['spm_amount']) ? trim(strip_tags($_POST['spm_amount'])) : '';
	
	$errcode = 0;
	$errmess = '';
    try
    {
// Открываем базу данных
		$db = App::me()->dbOpen();	

// Только зарегистрированные пользователи могут вносить данные
		if( !isset($_SESSION['user_id']) || $_SESSION['user_id'] == 0 )
			throw new Exception(ERR_M::TIMEOUT_ERROR, 999);
		$spm_user_id = $_SESSION['user_id'];
		
		if( !$art_id || !ctype_digit($art_id) || !$spm_id || !ctype_digit($spm_id) )
			throw new Exception(ERR_M::PROTOCOL_ERROR, 1);
			
//Есть ли разрешение на вставку записей
		$rwd = $_SESSION['priv']->specmodel->rwd;
		if( ($rwd & PERM_BITS::WRITE_ANY) == 0 ) throw new Exception(ERR_M::DATA_OPER_DISABLED, 99);

// Все ли данные переданы
		$errdata = "";
		
// uni_name			
		if( !$uni_name ) $errdata .= ($errdata?'<br>':'').'- Не указан шифр материала.';
		elseif( !$spm_uni_id || !ctype_digit( $spm_uni_id ) ) 
			$errdata .= ($errdata?'<br>':'').'- Не указан идентификатор материала.';
		else {
// Считываем данные из справочника
			$recset = $db->query('SELECT uni_name FROM units WHERE uni_id = '.$db->quote($spm_uni_id));                  
			$row = $recset->fetch(PDO::FETCH_ASSOC);
			if( !$row || $row['uni_name'] != $uni_name) {
				$errdata .= ($errdata?'<br>':'').'- Неправильно указан идентификатор материала.';
			}
			$recset->closeCursor();
		}

// spm_amount
		if( !$spm_amount )
			$errdata .= ($errdata?'<br>':'').'- Не указано количество материала.';
		else {
			$spm_amount = str_replace(',', '.', $spm_amount);
			if( !is_numeric( $spm_amount ) || $spm_amount <= 0 )
				$errdata .= ($errdata?'<br>':'')."- Неправильно указано количество материала.";
		}
		
//				
// Если есть ошибки - можно уже закончить
//
		if( $errdata ) throw new Exception($errdata, 1);
		
// Есть ли разрешение на апдейт этой записи
		if( $rwd & PERM_BITS::WRITE_OTH ) $where = '1 = 1';
		elseif( $rwd & PERM_BITS::WRITE_GRP ) 
			$where = 'spm_user_id IN (SELECT user_id FROM users WHERE cat_id = '.$_SESSION['cat_id'].')';
		elseif( $rwd & PERM_BITS::WRITE_OWN ) $where = 'spm_user_id = '.$_SESSION['user_id'];
		else $where = '1 = 0';
		$where .= ' AND spm_id = '.$db->quote($spm_id);
		
		$sqlreq = 'SELECT COUNT(*) AS count FROM specmodel WHERE '.$where.' LIMIT 1';
		$recset = $db->query( $sqlreq );		
		$row = $recset->fetch(PDO::FETCH_ASSOC);
		if( !$row['count'] ) {
			throw new Exception(ERR_M::DATA_OWNER_DISABLED, 99);
        }    
		$recset->closeCursor();
		
// Может быть материал уже существует
		$sqlreq =	'SELECT count(*) AS count FROM specmodel WHERE spm_uni_id = '.$db->quote($spm_uni_id).
					' AND spm_id != '.$db->quote($spm_id).' AND spm_art_id = '.$db->quote($art_id);
		$recset = $db->query( $sqlreq );		
		$row = $recset->fetch(PDO::FETCH_ASSOC);
		if( $row['count'] != 0 ) {
			throw new Exception('В спецификации уже присутствует запись с шифром "'.$uni_name.'"', 1);
        }    
		$recset->closeCursor();

// Пишем данные
        $sqlreq =   'UPDATE specmodel SET '.
					'spm_art_id = '.$db->quote($art_id).", ".
					'spm_uni_id = '.$db->quote($spm_uni_id).", ".
					'spm_amount = '.$db->quote($spm_amount)." ".
					'WHERE spm_id = '.$db->quote($spm_id);
					
		$db->exec($sqlreq);
    }
	catch (PDOException $e) {
		$errcode = 1;
		$errmess = ERR_M::DATABASE_ERROR;
	}
    catch ( Exception $e ) {
		$errcode = $e->getCode();
		$errmess = $e->getMessage();
	}

	return array('errcode'=>$errcode,'errmess'=>$errmess);
  }

  
  public function deluni() {
    $errmess = "";
	$errcode = 0;
		
    $spm_ids = (isset($_REQUEST['id']) && $_REQUEST['id'] != '') ?
        explode(",", $_REQUEST["id"], 100) : array();

    try
    {
// Только зарегистрированные пользователи могут удалять данные
		if( !isset($_SESSION['user_id']) || $_SESSION['user_id'] == 0 )
			throw new Exception(ERR_M::TIMEOUT_ERROR, 999);

// Есть ли разрешение на удаление хоть какой либо записи
		$rwd = $_SESSION['priv']->specmodel->rwd;
		if( ($rwd & PERM_BITS::DELETE_ANY) == 0 ) throw new Exception(ERR_M::DATA_OPER_DISABLED, 99);
		
        if (!Tools::is_numeric_array( $spm_ids ))
			throw new Exception(ERR_M::PROTOCOL_ERROR, 1);
        
		$spm_id_list = implode(',', $spm_ids);

// Открываем базу данных
		$db = App::me()->dbOpen();	

// Есть ли разрешение на удаление этих записей
		if( $rwd & PERM_BITS::DELETE_OTH ) $where = '1 = 1';
		elseif( $rwd & PERM_BITS::DELETE_GRP ) 
			$where = 'spm_user_id IN (SELECT user_id FROM users WHERE cat_id = '.$_SESSION['cat_id'].')';
		elseif( $rwd & PERM_BITS::DELETE_OWN ) $where = 'spm_user_id = '.$_SESSION['user_id'];
		else $where = '1 = 0';
		$where .= ' AND spm_id IN ('.$spm_id_list.')';
		
		$sqlreq = 'SELECT COUNT(*) AS count FROM specmodel WHERE '.$where;
		$recset = $db->query( $sqlreq );		
		$row = $recset->fetch(PDO::FETCH_ASSOC);
		if( $row['count'] != count($spm_ids) ) {
			throw new Exception(ERR_M::DATA_OWNER_DISABLED, 99);
        }    
		$recset->closeCursor();
		
// Удаляем записи из справочника
        $sqlreq = "DELETE FROM specmodel WHERE spm_id IN (".$spm_id_list.")";
        $db->exec($sqlreq);
	}
	catch (PDOException $e) {
		$errcode = 1;
		$errmess = ERR_M::DATABASE_ERROR;
	}
    catch ( Exception $e ) {
		$errcode = $e->getCode();
		$errmess = $e->getMessage();
	}

	return array('errcode'=>$errcode,'errmess'=>$errmess);
  }
  
    public function copyuni() {

    $art_id			= isset($_POST['art_id']) ? trim(strip_tags($_POST['art_id'])) : '';
    $from_id		= isset($_POST['from_id']) ? trim(strip_tags($_POST['from_id'])) : '';
    $from_num		= isset($_POST['from_num']) ? trim(strip_tags($_POST['from_num'])) : '';
	
	$errcode = 0;
	$errmess = '';
    try
    {
// Только зарегистрированные пользователи могут вносить данные
		if( !isset($_SESSION['user_id']) || $_SESSION['user_id'] == 0 )
			throw new Exception(ERR_M::TIMEOUT_ERROR, 999);
		$spm_user_id = $_SESSION['user_id'];
		
// Все ли данные переданы
		if( !$art_id || !ctype_digit($art_id) || 
			!$from_id || !ctype_digit($from_id) || 
			!$from_num || !ctype_digit($from_num) )
			throw new Exception(ERR_M::PROTOCOL_ERROR, 1);
			
// Есть ли разрешение на вставку записей в спецификацию
		$rwd = $_SESSION['priv']->specmodel->rwd;
		if( ($rwd & PERM_BITS::WRITE_OWN) == 0 ) throw new Exception(ERR_M::DATA_OPER_DISABLED, 99);

// Открываем базу данных
		$db = App::me()->dbOpen();	

// Сколько всего записей в спецификации
		$rs = $db->query( "SELECT COUNT(*) as count FROM specmodel WHERE spm_art_id = ${from_id}" );
		$from_all = $rs->fetchObject()->count;
		if( $from_all === 0 ) 
			throw new Exception(ERR_M::SUCCESS, 0);
		$rs->closeCursor();
		
// Получаем количество записей с учетом привилегий
		$whc = array();
		$whc[] = 'spm_art_id = '.$db->quote($from_id);
		
		if( $rwd & PERM_BITS::READ_OTH ) $whc[] = '1 = 1';
		elseif( $rwd & PERM_BITS::READ_GRP ) 
			$whc[] = 'spm_user_id IN (SELECT user_id FROM users WHERE cat_id = '.$_SESSION['cat_id'].')';
		elseif( $rwd & PERM_BITS::READ_OWN ) $whc[] = 'spm_user_id = '.$_SESSION['user_id'];
		else $whc[] = '1 = 0';
		
        $where = implode(" AND ", $whc);
		unset($whc);

        $rs = $db->query( "SELECT COUNT(*) AS count FROM specmodel WHERE ".$where );
		$from_acc = $rs->fetchObject()->count;
		$rs->closeCursor();
		
// Все ли доступно 
		if( $from_all != $from_acc ) 
			throw new Exception("У Вас недостаточно прав для копирования выбранной спецификации.", 0);
            
// Копируем спецификацию
		$sel_to = $db->prepare( "SELECT spm_id FROM specmodel WHERE spm_art_id = :art_id AND spm_uni_id = :uni_id FOR UPDATE");
		$upd_to = $db->prepare( "UPDATE specmodel SET spm_amount = spm_amount + :spm_amount WHERE spm_id = :spm_id" );
		$ins_to = $db->prepare( "INSERT specmodel SET spm_art_id = :spm_art_id, spm_uni_id = :spm_uni_id, ".
								"spm_amount = :spm_amount, spm_user_id = :spm_user_id" );
		try {
			$frs = $db->query( "SELECT * FROM specmodel WHERE spm_art_id = ${from_id}" );
			$db->beginTransaction();
			while( $frow = $frs->fetchObject() ) {
				$sel_to->execute( array( ':art_id'=>$art_id, 'uni_id'=>$frow->spm_uni_id ) );
				if( $trow = $sel_to->fetchObject() ) 
					$upd_to->execute( array( 'spm_id'=>$trow->spm_id, 'spm_amount'=>$frow->spm_amount * $from_num ) );
				else
					$ins_to->execute( array( 'spm_art_id' => $art_id, 'spm_uni_id' => $frow->spm_uni_id, 
								'spm_amount' => $frow->spm_amount * $from_num, 'spm_user_id' => $spm_user_id) );
				$sel_to->closeCursor();
			}
			$db->commit();
			$frs->closeCursor();
		}
		catch (PDOException $e) {
			$db->rollback();
			$errcode = 1;
			$errmess = ERR_M::DATABASE_ERROR;
		}
    }
	catch (PDOException $e) {
		$errcode = 1;
		$errmess = ERR_M::DATABASE_ERROR;
	}
    catch ( Exception $e ) {
		$errcode = $e->getCode();
		$errmess = $e->getMessage();
	}

	return array('errcode'=>$errcode,'errmess'=>$errmess);
  }


}
?>